package cn.shop.admin.component.withdraw.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.shop.admin.component.withdraw.AliConfig;
import cn.shop.admin.component.withdraw.WithdrawStrategy;
import cn.shop.admin.entity.backPaymentChannelModule.WithdrawAlipayChannel;
import cn.shop.admin.req.BatchWithdrawReq;
import cn.shop.admin.service.WithdrawAlipayChannelService;
import cn.shop.admin.service.WithdrawService;
import cn.shop.transcation.withdraw.entity.Withdraw;
import cn.shop.utils.enums.ProcessState;
import cn.shop.utils.enums.WithdrawAccountType;
import cn.shop.utils.enums.WithdrawSolution;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
import com.alipay.api.domain.Participant;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 支付宝结算
 *
 * @author lyh
 * @since 2021-11-11 10:10
 */
@Component
public class AlipayPaymentStrategy implements WithdrawStrategy {

	@Resource
	private WithdrawService withdrawService;

	@Resource
	private AliConfig config;

	@Resource
	private WithdrawAlipayChannelService channelService;

	@Resource
	private AsyncTaskExecutor asyncTaskExecutor;


	private static final Logger LOG = LoggerFactory.getLogger(AlipayPaymentStrategy.class);

	/**
	 * 获取当前提现类型标识
	 *
	 * @return 提现类型标识
	 * @since 2021/11/11 10:36
	 */
	@Override
	public int getType() {
		return 2;
	}

	/**
	 * 订单结算
	 *
	 * @param batchWithdrawReq 订单id
	 * @since 2021/11/11 10:09
	 */
	@Override
	public boolean settlement(BatchWithdrawReq batchWithdrawReq) {
		asyncTaskExecutor.submit(() -> {
			LOG.info("异步支付任务开始");
			executePay(batchWithdrawReq);
			LOG.info("异步支付任务结束");
		});
		return true;
	}

	private void executePay(BatchWithdrawReq batchWithdrawReq) {
		LambdaQueryWrapper<Withdraw> query = Wrappers.lambdaQuery();
		List<Withdraw> withdraws = withdrawService.list(query.in(Withdraw::getId, batchWithdrawReq.getIds())
				.eq(Withdraw::getAccountType, WithdrawAccountType.ALIPAY_PAYMENT)
				.eq(Withdraw::getState, ProcessState.UNTREATED));
		WithdrawAlipayChannel channel = channelService.getById(batchWithdrawReq.getId());
		AlipayClient client;
		try {
			client = new DefaultAlipayClient(certAlipayRequest(channel));
		} catch (AlipayApiException e) {
			LOG.warn("创建阿里客户端失败", e);
			withdraws.forEach(w -> {
				w.setState(ProcessState.ABNORMAL);
				w.setExceptionInfo("支付宝支付系统出错");
				w.setSolution(WithdrawSolution.AUTOMATIC_PAYMENT);
			});
			withdrawService.updateBatchById(withdraws);
			return;
		}
		if (CollectionUtil.isNotEmpty(withdraws)) {
			withdraws.forEach(e -> {
				pay(client, e);
				e.setSolution(WithdrawSolution.AUTOMATIC_PAYMENT);
			});
		}
		withdrawService.updateBatchById(withdraws);
	}

	private void pay(AlipayClient client, Withdraw withdraw) {
		AlipayFundTransUniTransferRequest req = new AlipayFundTransUniTransferRequest();
		req.setBizModel(createModel(withdraw));
		withdraw.setSolution(WithdrawSolution.AUTOMATIC_PAYMENT);
		try {
			AlipayFundTransUniTransferResponse res = client.certificateExecute(req);
			if (!StrUtil.equals(res.getCode(), "10000")) {
				withdraw.setState(ProcessState.ABNORMAL);
				withdraw.setExceptionInfo(res.getSubMsg());
				return;
			}
			withdraw.setState(ProcessState.COMPLETED);
			withdraw.setPaymentTime(LocalDateTime.now());
		} catch (AlipayApiException e) {
			LOG.warn("付款接口错误", e);
			withdraw.setState(ProcessState.ABNORMAL);
			withdraw.setExceptionInfo("系统错误");
		}
	}

	private AlipayFundTransUniTransferModel createModel(Withdraw withdraw) {
		AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();
		model.setBizScene("DIRECT_TRANSFER");
		model.setOrderTitle("提现");
		model.setOutBizNo(String.valueOf(withdraw.getId()));
		model.setTransAmount(withdraw.getActualAmount().toString());
		model.setProductCode("TRANS_ACCOUNT_NO_PWD");
		model.setPayeeInfo(createParticipant(withdraw));
		model.setRemark("提现" + model.getTransAmount());
		return model;
	}

	private Participant createParticipant(Withdraw withdraw) {
		Participant part = new Participant();
		part.setIdentity(withdraw.getAccount());
		part.setIdentityType("ALIPAY_LOGON_ID");
		part.setName(withdraw.getBankAccountName());
		// if (withdraw.getType() == 1) {
		// 	MerchantUser user = merchantUserService.getById(withdraw.getUserId());
		// 	part.setName(user.getName());
		// }
		// else {
		// 	FrontUser user = frontUserService.getById(withdraw.getUserId());
		// 	part.setName(user.getName());
		// }
		return part;
	}

	public CertAlipayRequest certAlipayRequest(WithdrawAlipayChannel channel) {
		CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
		//设置网关地址
		certAlipayRequest.setServerUrl(config.getGatewayUrl());
		//设置应用Id
		certAlipayRequest.setAppId(channel.getAppId());
		//设置应用私钥
		certAlipayRequest.setPrivateKey(channel.getPrivateKey());
		//设置请求格式，固定值json
		certAlipayRequest.setFormat("json");
		//设置字符集
		certAlipayRequest.setCharset(config.getCharset());
		//设置签名类型
		certAlipayRequest.setSignType(config.getSignType());
		//设置应用公钥证书路径
		certAlipayRequest.setCertContent(new String(channel.getAppCertPath()));
		//设置支付宝公钥证书路径
		certAlipayRequest.setAlipayPublicCertContent(new String(channel.getAlipayCertPath()));
		//设置支付宝根证书路径
		certAlipayRequest.setRootCertContent(new String(channel.getAlipayRootCertPath()));
		return certAlipayRequest;
	}
}
